from fileinput import filename
import logging
import json
import urllib.request
import urllib.parse
import requests
from urllib3 import encode_multipart_formdata
import pathlib

class GdprinterMqtt:
  @classmethod
  def get_component_desc(cls):
    return "GdprinterMqtt"  
  def __init__(self, config):
    self.server = config.get_server()
    self.kapis = self.server.load_component(config, "klippy_apis")
    self.mqtt = self.server.load_component(config, "mqtt")
    self.qos = config.getint("qos", None, minval=0, maxval=2)
    self.file_manager = self.server.load_component(config, "file_manager")
    self.http = self.server.load_component(config, "http_client")
    app_args = self.server.get_app_args()
    self.datapath = app_args["data_path"]
    self.last_print_stats = {}
    self.order_info = {}
    # 订阅mqtt主题
    self.mqtt.subscribe_topic(
      "order/print",
      self._handle_mqtt,
      self.qos
    )

    # 添加状态监听
    self.server.register_event_handler("server:klippy_ready", self._handle_ready)
    self.server.register_event_handler("server:error", self._handle_error)
    self.server.register_event_handler("server:status_update", self._handle_status_update)
    self.server.register_event_handler("printer:state_changed", self._handle_printer_state_changed)
    self.server.register_event_handler("update_manager:update_refreshed", self._handle_update_refreshed)

    # 注册定时状态检测
    self.status_timer = self.server.get_event_loop().register_timer(
      self._check_printer_status
    )
  async def getConfig(self, section, option):
    cfg_status = await self.kapis.query_objects({'configfile': None})
    config = cfg_status.get('configfile', {}).get('config', {})
    printer_cfg = config.get(section, {})
    serial = printer_cfg.get(option, "None")
    return serial
  async def _handle_update_refreshed(self, update):
    logging.info(f"Update refreshed: {update}")
  async def _handle_mqtt(self, payload):
    # 解析数据
    try:
      param = payload.decode()
      p = json.loads(param)
      serial = await self.getConfig("mcu", "serial")
      logging.info(f"mcu:{serial}")
      if p["serial"] != serial:
        return
      if p['command'] == 'print':
        url = p["model_url"]
        filename = f"{p['model_name']}.gcode"
        dest_path = f"{self.datapath}/gcodes/{filename}"
        await self.http.download_file(
            url,
            "application/octet-stream",
            dest_path
        )
        
        await self.kapis.start_print(filename)
        await self.mqtt.publish_topic(
          "order/status",
          "start print",
          self.qos
        )
        logging.info("打印任务处理完成")
      elif p['command'] == 'pause':
        logging.info("开始暂停打印任务")
        await self.kapis.pause_print()
        logging.info("打印任务暂停完成")
      else:
        logging.info(param)
    except Exception as e:
      logging.error(f"打印任务处理失败: {e}")

  async def _handle_ready(self):
    logging.info("Server klippy is ready")
    await self.mqtt.publish_topic(
      "order/status",
      "Server ready",
      self.qos
    )
    # 启动状态定时检测器
    self.status_timer.start()

  # **
  # 处理Klipper错误事件
  # **  
  async def _handle_error(self, error):
    logging.error(f"Klipper error: {error}")
    await self.mqtt.publish_topic(
      "order/status",
      "error",
      self.qos
    )

  # **
  # 处理打印机状态变更事件
  # **
  async def _handle_printer_state_changed(self, state):
    logging.info(f"Printer state changed: {state}")
    await self.mqtt.publish_topic(
      "printer/status",
      state,
      self.qos
    )  
  # **
  # 检查打印机状态
  # **
  async def _check_printer_status(self, eventtime):
    try:
      logging.info("开始检查打印机状态")
      # 获取打印状态
      print_stats = await self.kapis.query_objects({'print_stats': None})
      print_stats = print_stats.get('print_stats', {})
      # 检查打印状态是否发生变化
      await self._handle_status_update({'print_stats': print_stats})
    except Exception as e:
      logging.error(f"检查打印机状态失败: {e}") 
    return eventtime + 30

  # **
  # 处理打印状态变更事件  
  # **
  async def _handle_status_update(self, status):
    if 'print_stats' not in status:
      return
    logging.info(f"开始处理打印状态: {json.dumps(status)}")  
    print_stats = status['print_stats']
    state = print_stats.get('state', 'unknown')
    filename = print_stats.get('filename', '')
    serial = await self.getConfig("mcu", "serial")
    logging.info(f"mcu:{serial}")
    if state == 'unknown':
      return    
    if state == 'printing':
      self.order_info['filename'] = print_stats['filename']
    # 发送状态变更通知
    msg = {
        "state": print_stats.get('state', 'unknown'),
        "filename": self.order_info.get('filename', ''),
        'filename_origin': print_stats.get('filename', ''),
        "progress": print_stats.get('progress', 0),
        "total_time": print_stats.get('total_time', 0),
        "serial": serial
    }
    await self.mqtt.publish_topic(
      "order/status",
      json.dumps(msg),
      self.qos
    )
    self.last_print_stats = print_stats.copy()
def load_component(config):
  return GdprinterMqtt(config)            